// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()


//在 app.js 的全局错误级别中间件中，捕获验证失败的错误，并把验证失败的结果响应给客户端：
const joi = require('joi')

// 导入配置文件
const config = require('./config')
// 解析 token 的中间件
const { expressjwt } = require('express-jwt')

//============================    【中间件数据预处理】    ========================================================
// 导入 cors 中间件
const cors = require('cors')
// 将 cors 注册为全局中间件
app.use(cors())

//配置解析 `application/x-www-form-urlencoded` 格式的表单数据的中间件
app.use(express.urlencoded({ extended: false }))
//配置解析 `JSON` 格式的表单数据的中间件
app.use(express.json())

// 2.4 优化 res.send() 代码
// 响应数据的中间件
app.use(function (req, res, next) {
  // status = 0 为成功； status = 1 为失败； 默认将 status 的值设置为 1，方便处理失败的情况
  res.cc = (err, status = 1) => {
    res.send({
      status,
      // 状态描述，判断 err 是 错误对象 还是 字符串
      message: err instanceof Error ? err.message : err
    })
  }
  next()
})

// TODO_04：注册将 JWT 字符串解析还原成 JSON 对象的中间件

//  解析成功之后会把用户信息  挂载到req.auth(原来是req.user) 上,auth内的属性是加密时的对象确定的如s_user。

//使用加密字符串，算法为HS256,进行解析，除非访问路径是 /api/
/**
 * HS256 使用同一个「secret_key」进行签名与验证（对称加密）。一旦 secret_key 泄漏，就毫无安全性可言了。
 * 因此 HS256 只适合集中式认证，签名和验证都必须由可信方进行。
 *  传统的单体应用广泛使用这种算法，但是请不要在任何分布式的架构中使用它
 * 
 * userProperty: "auth" 使用req.auth获取用户信息
 */
//,algorithms:['HS256']
app.use(
  expressjwt({
    secret: config.jwtSecretKey,
    algorithms: ['HS256'],
    userProperty: "auth"
  }).unless({
    path: [/^\/api\//]
  })
)
app.use('/uploads', express.static('./uploads'))
// write your code here...
//==========================    【路由】    =============================================

// 导入并注册用户路由模块
const userRouter = require('./router/user')
app.use('/api', userRouter)

const userinfo_Router = require('./router/userinfo')
app.use('/my', userinfo_Router)

const artCateRouter = require('./router/artcate')
app.use('/my/article', artCateRouter)

const articleRouter = require('./router/article')
app.use('/my/article',articleRouter)



//==================    【错误捕获】    ===============================

// 错误中间件
app.use((err, req, res, next) => {
  //Validation n. 验证；确认，批准，生效；肯定，认可
  //err instanceof joi.ValidationError 测试err是否是joi.ValidationError 的一个实例
  if (err instanceof joi.ValidationError) {
    return res.cc(err)
  }
  // 捕获身份认证失败的错误
  if (err.name === 'UnauthorizedError') {
    return res.cc('身份认证失败！')
  }
  res.cc(err)
  next()
})

// 调用 app.listen 方法，指定端口号并启动web服务器
app.listen(8080, function () {
  console.log('api server running at http://127.0.0.1:8080')
})